/*
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/

module dlua.lauxlib;
extern (C) {

private import std.c.stddef, 
               std.c.stdio, 
               dlua.lua, 
               dlua.luaconf;

/+++++
version (LUA_COMPAT_GETN) {
	int luaL_getn (lua_State* L, int t);
	void luaL_setn (lua_State* L, int t, int n);
} else {
	int luaL_getn (lua_State* L, int i) { return lua_objlen(L, i); }
	void luaL_setn (lua_State* L, int i, int j) {}
}

version (LUA_COMPAT_OPENLIB) {
	alias luaL_openlib luaI_openlib;
}
+++++/


/* extra error code for `luaL_load' */
const int LUA_ERRFILE = LUA_ERRERR + 1;


struct luaL_Reg {
  char* name;
  lua_CFunction func;
}


void luaI_openlib (lua_State* L, in char* libname, in luaL_Reg* l, int nup);
void luaL_register (lua_State* L, in char* libname, in luaL_Reg* l);
int luaL_getmetafield (lua_State* L, int obj, in char* e);
int luaL_callmeta (lua_State* L, int obj, in char* e);
int luaL_typerror (lua_State* L, int narg, in char* tname);
int luaL_argerror (lua_State* L, int numarg, in char* extramsg);
char* luaL_checklstring (lua_State* L, int numArg, size_t* l);
char* luaL_optlstring (lua_State* L, int numArg, in char* def, size_t* l);
lua_Number luaL_checknumber (lua_State* L, int numArg);
lua_Number luaL_optnumber (lua_State* L, int nArg, lua_Number def);

lua_Integer luaL_checkinteger (lua_State* L, int numArg);
lua_Integer luaL_optinteger (lua_State* L, int nArg, lua_Integer def);

void luaL_checkstack (lua_State* L, int sz, in char* msg);
void luaL_checktype (lua_State* L, int narg, int t);
void luaL_checkany (lua_State* L, int narg);

int luaL_newmetatable (lua_State* L, in char* tname);
void* luaL_checkudata (lua_State* L, int ud, in char* tname);

void luaL_where (lua_State* L, int lvl);
int luaL_error (lua_State* L, in char* fmt, ...);

int luaL_checkoption (lua_State* L, int narg, in char* def, in char* [] lst);

int luaL_ref (lua_State* L, int t);
void luaL_unref (lua_State* L, int t, int ref);

int luaL_loadfile (lua_State* L, in char* filename);
int luaL_loadbuffer (lua_State* L, in char* buff, size_t sz, in char* name);

int luaL_loadstring (lua_State* L, in char* s);

lua_State* luaL_newstate ();


char* luaL_gsub (lua_State* L, in char* s, in char* p, in char* r);

char* luaL_findtable (lua_State* L, int idx, in char* fname, int szhint);




/*
** ===============================================================
** some useful macros
** ===============================================================
*/

//#define luaL_argcheck(L, cond,numarg,extramsg)	\
//		((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))

void luaL_argcheck (lua_State* L, int cond, int narg, in char* extramsg) { cond || luaL_argerror(L, narg, extramsg); }
char* luaL_checkstring (lua_State* L, int n) { return luaL_checklstring(L, n, null); }
char* luaL_optstring (lua_State* L, int n, char* d) { return luaL_optlstring (L, n, d, null); }
int luaL_checkint (lua_State* L, int n) { return cast(int)luaL_checkinteger(L, n); }
int luaL_optint (lua_State* L, int n, int d) { return cast(int)luaL_optinteger(L, n, d); }
int luaL_checklong (lua_State* L, int n) { return cast(int)luaL_checkinteger(L, n); }
int luaL_optlong (lua_State* L, int n, int d) { return cast(int)luaL_optinteger(L, n, d); }

char* luaL_typename (lua_State* L, int i) { return lua_typename(L, lua_type(L, i)); }

int luaL_dofile (lua_State* L, in char* fn) { return (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)); }

int luaL_dostring (lua_State* L, in char* s) { return (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)); }

void luaL_getmetatable (lua_State* L, in char* n) { lua_getfield(L, LUA_REGISTRYINDEX, n); }


// void luaL_opt (lua_State* L, lua_CFunction f, int n, int d) { lua_isnoneornil(L, n) ? d : f(L, n); }

/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/



struct luaL_Buffer {
  char *p;			/* current position in buffer */
  int lvl;  /* number of strings in the stack (level) */
  lua_State *L;
  char[LUAL_BUFFERSIZE] buffer;
}

//#define luaL_addchar(B,c) \
//  ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
//  (*(B)->p++ = (char)(c)))

/* compatibility only */
// #define luaL_putchar(B,c)	luaL_addchar(B,c)

void luaL_addsize (luaL_Buffer* B, int n) { B.p += n; }

void luaL_buffinit (lua_State* L, luaL_Buffer* B);
char* luaL_prepbuffer (luaL_Buffer* B);
void luaL_addlstring (luaL_Buffer* B, in char* s, size_t l);
void luaL_addstring (luaL_Buffer* B, in char* s);
void luaL_addvalue (luaL_Buffer* B);
void luaL_pushresult (luaL_Buffer* B);


/* }====================================================== */


/* compatibility with ref system */

/* pre-defined references */
const int LUA_NOREF = -2;
const int LUA_REFNIL = -1;

// #define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
// (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))

void lua_unref (lua_State* L, int ref) { luaL_unref(L, LUA_REGISTRYINDEX, ref); }

void lua_getref (lua_State* L, int ref) { lua_rawgeti(L, LUA_REGISTRYINDEX, ref); }


alias luaL_Reg luaL_reg;


} // extern (C)